<?php

declare(strict_types=1);

namespace Zms\Enums;

use ReflectionClass;
use ReflectionClassConstant;
use ReflectionException;
use Zms\Unit\Arr;

/**
 * 注解工具类
 */
class Annotate
{
    private static array $cache = [];

    /**
     * 注解获取器
     * @param $class
     * @return array{class:array,method:array,constant:array,propertie:array}
     */
    public static function getClassAnnotate($class): array
    {
        if (isset(self::$cache[$class])) {
            return self::$cache[$class];
        }
        try {
            $annotate = ['class' => [], 'method' => [], 'constant' => [], 'propertie' => []];
            $ref = new ReflectionClass($class);
            foreach ($ref->getAttributes() as $attributes) {
                $className = $attributes->getName();
                if ($className) {
                    $annotate['class'][$className] = $attributes->getArguments();
                }
            }
            foreach ($ref->getMethods() as $methods) {
                $methodName = $methods->getName();
                foreach ($methods->getAttributes() as $method) {
                    $className = $method->getName();
                    $annotate['method'][$methodName][$className] = $method->getArguments();
                }
            }
            foreach ($ref->getProperties() as $propertie) {
                $propertieName = $propertie->getName();
                foreach ($propertie->getAttributes() as $attribute) {
                    $className = $attribute->getName();
                    $annotate['propertie'][$propertieName][$className] = $attribute->getArguments();
                }
            }
            foreach ($ref->getConstants() as $key => $item) {
                $constants = new ReflectionClassConstant($class, $key);
                foreach ($constants->getAttributes() as $constants) {
                    $className = $constants->getName();
                    if ($className) {
                        $annotate['constant'][$key][$className] = Arr::merge(['value' => $ref->getConstant($key)], $constants->getArguments());
                    }
                }
            }
            self::$cache[$class] = $annotate;
            return $annotate;
        } catch (ReflectionException) {
            return ['class' => [], 'method' => [], 'constant' => [], 'propertie' => []];
        }
    }
}